﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;

/* CommandBuffer基本应用 https://www.cnblogs.com/llstart-new0201/p/12630384.html
 * CommandBuffer为渲染命令缓冲区，我们将一些列渲染指令添加到CommandBuffer中，
 * 在需要执行时通过Camera或者Graphics类进行执行，进而实现对渲染流程的控制。
 * 同时可以实时生成我们需要的临时效果。
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 * 
 */
namespace Example03_Demo01
{
    public enum CameraCmdBuffer
    {
        DRAW_RENDERER,
        DRAW_RENDERER_TARGET,
        DRAW_MESH,
        DRAW_MESH_TARGET
    }

    public class Demo01 : MonoBehaviour
    {
        public Camera mainCamera;
        public Material cmdMat;
        public Renderer cubeRenderer;
        public RenderTexture target;
        public Color clearColor = Color.red;
        public int triCount = 6;
        public float radius = 5;

        private CommandBuffer cmdBuffer;
        private Mesh mesh;

        //(1)ToScreen
        //入口参数cubeRenderer为一个立方体网格，cmdMat为一个unlit/texture的材质，相当于用cmdMat材质，对cubeRenderer的显示效果进行了重新生成。
        //并将结果直接显示在屏幕上，位置为原cubeRenderer位置。
        public void DrawRenderer()
        {
            cmdBuffer.Clear();
            cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
        }

        //(2)ToTarget
        //此方法相当于在将(1)的计算结果绘制到一个RenderTexture类型的target上，将此Target可以赋值给其他对象上，如RawImage等。
        public void DrawRendererToTarget()
        {
            cmdBuffer.Clear();
            cmdBuffer.SetRenderTarget(target);
            cmdBuffer.ClearRenderTarget(true, true, clearColor);
            cmdBuffer.DrawRenderer(cubeRenderer, cmdMat);
        }
        //(3) DrawMesh  ToScreen
        //表示将mesh根据cmdMat材质定义的效果绘制到屏幕上，如果不需要坐标变换则采用 Matrix4x4.identity矩阵。
        public void DrawMesh()
        {
            cmdBuffer.Clear();
            cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
        }
        //(4) DrawMesh ToTarget
        //此方法相当于在将(3)的计算结果绘制到一个RenderTexture类型的target上，将此Target可以赋值给其他对象上，如RawImage等。
        public void DrawMeshToTarget()
        {
            cmdBuffer.Clear();
            cmdBuffer.SetRenderTarget(target);
            cmdBuffer.ClearRenderTarget(true, true, clearColor);

            cmdBuffer.DrawMesh(mesh, Matrix4x4.identity, cmdMat);
        }

        private void Start()
        {
            cmdBuffer = new CommandBuffer() { name = "CameraCmdBuffer" };

            mainCamera.AddCommandBuffer(CameraEvent.AfterForwardOpaque, cmdBuffer);
            /*
             * 上述代码表示将此指令添加到Camera的执行序列中，即当渲染完不透明物体时执行此指令。
             * 此指令渲染的结果可能绘制到屏幕上，也可能绘制到一个RenderTexture上。
             */

            if (mesh == null)
            {
                mesh = Graphics00Mesh.Instance.GetMesh(triCount, radius);
            }
        }

        private void OnValidate()
        {
            mesh = Graphics00Mesh.Instance.GetMesh(triCount, radius);
        }

        private void OnDisable()
        {
            mainCamera.RemoveAllCommandBuffers();
        }
    }
}